import "package:flutter/material.dart";

/// 自定义NestedScrollView 的 滚动控制器
/// 用于处理 NestedScrollView 与 tabBarView(懒加载) 嵌套滚动场景
class NestedInnerScrollController extends ScrollController {
  ScrollController? _inner;
  NestedInnerScrollController();

  /// 重写 createScrollPosition、attach、detach 方法，为了实现原NestedScrollView与tabBarView滚动联动
  @override
  ScrollPosition createScrollPosition(ScrollPhysics physics,
      ScrollContext context, ScrollPosition? oldPosition) {
    ScrollPosition scrollPosition;
    ScrollableState? scrollableState = context as ScrollableState?;
    if (scrollableState != null) {
      _inner = PrimaryScrollController.maybeOf(scrollableState.context);
    }
    if (_inner == null) {
      scrollPosition =
          super.createScrollPosition(physics, context, oldPosition);
    } else {
      scrollPosition =
          _inner!.createScrollPosition(physics, context, oldPosition);
    }
    return scrollPosition;
  }

  @override
  void attach(ScrollPosition position) {
    super.attach(position);
    _inner?.attach(position);
  }

  @override
  void detach(ScrollPosition position) {
    _inner?.detach(position);
    super.detach(position);
  }

  /// 解除所有_inner，重新绑定对应tab的tabBarView的位置，解决其他tabBarView滚动收到当前tabBarView的影响问题
  void attachCurrent() {
    if (_inner != null) {
      while (_inner!.positions.isNotEmpty) {
        _inner!.detach(_inner!.positions.first);
      }
      _inner!.attach(position);
    }
  }

  /// 获取当前上下文的 InnerScrollController，没有则抛出异常
  static ScrollController? of(BuildContext context) {
    final _InheritedInnerScrollController? target = context
        .dependOnInheritedWidgetOfExactType<_InheritedInnerScrollController>();
    assert(target != null, 'No InnerScrollController found in context');
    return target!.controller;
  }

  /// 获取当前上下文的 InnerScrollController，没有则返回null
  static ScrollController? maybeOf(BuildContext context) {
    return context
        .dependOnInheritedWidgetOfExactType<_InheritedInnerScrollController>()
        ?.controller;
  }
}

// 自定义Nested的TabBarView
class NestedTabBarView extends StatefulWidget {
  final TabController? controller; //外部关联的tabBar 控制器
  final List<Widget> children; //每个tabBarView 内容

  const NestedTabBarView({
    super.key,
    required this.children,
    this.controller,
  });

  @override
  State<NestedTabBarView> createState() => _NestedTabBarViewState();
}

class _NestedTabBarViewState extends State<NestedTabBarView> {
  List<NestedInnerScrollController> _nestedInnerControllers = [];

  @override
  void initState() {
    super.initState();
    _initNestedInnerControllers(); //初始化内部滚动控制器
    widget.controller?.addListener(onTapChange); //监听 tabBar tabChange事件
  }

  @override
  void dispose() {
    widget.controller?.removeListener(onTapChange); //移除监听 tabBar tabChange事件
    _disposeNestedInnerControllers(); //销毁内部滚动控制器
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant NestedTabBarView oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 子组件数量变化时重新初始化内部滚动控制器
    if (widget.children.length != oldWidget.children.length) {
      _initNestedInnerControllers();
    }
  }

  void _initNestedInnerControllers() {
    _disposeNestedInnerControllers();
    var controllers = List.generate(
        widget.children.length, (index) => NestedInnerScrollController());
    if (mounted) {
      // 如果组件已挂载，则更新状态
      setState(() {
        _nestedInnerControllers = controllers;
      });
    } else {
      // 如果组件未挂载，则直接赋值
      _nestedInnerControllers = controllers;
    }
  }

  void _disposeNestedInnerControllers() {
    for (var element in _nestedInnerControllers) {
      element.dispose();
    }
  }

  void onTapChange() {
    // 当前tabBar 的 index
    int index = widget.controller!.index;
    // 如果动画值等于索引，说明切换完成，此时重新关联滚动控制器
    if (index == widget.controller!.animation?.value) {
      _nestedInnerControllers[index].attachCurrent();
    }
  }

  @override
  Widget build(BuildContext context) {
    return TabBarView(
      controller: widget.controller,
      children: List.generate(
        widget.children.length,
        (index) => _InheritedInnerScrollController(
          controller: _nestedInnerControllers[index],
          child: widget.children[index],
        ),
      ),
    );
  }
}

/// 共享 ScrollController
class _InheritedInnerScrollController extends InheritedWidget {
  final ScrollController controller;
  const _InheritedInnerScrollController({
    required super.child,
    required this.controller,
  });

  @override
  bool updateShouldNotify(covariant _InheritedInnerScrollController oldWidget) {
    return controller != oldWidget.controller;
  }
}
